<!DOCTYPE HTML>
<html lang="zh-CN">


<head>
    <meta charset="utf-8">
    <meta name="keywords" content="go,supervisor,源码,python">
    <meta name="description" content="简单童真">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta name="renderer" content="webkit|ie-stand|ie-comp">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <!-- Global site tag (gtag.js) - Google Analytics -->


    <title>supervisor源码解析 | JacksonYoudi</title>
    <link rel="icon" type="image/png" href="/medias/mj-moon.png">

    <link rel="stylesheet" type="text/css" href="/libs/awesome/css/all.css">
    <link rel="stylesheet" type="text/css" href="/libs/materialize/materialize.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/aos/aos.css">
    <link rel="stylesheet" type="text/css" href="/libs/animate/animate.min.css">
    <link rel="stylesheet" type="text/css" href="/libs/lightGallery/css/lightgallery.min.css">
    <link rel="stylesheet" type="text/css" href="/css/matery.css">
    <link rel="stylesheet" type="text/css" href="/css/my.css">

    <script src="/libs/jquery/jquery.min.js"></script>

<meta name="generator" content="Hexo 5.4.0">
<style>.github-emoji { position: relative; display: inline-block; width: 1.2em; min-height: 1.2em; overflow: hidden; vertical-align: top; color: transparent; }  .github-emoji > span { position: relative; z-index: 10; }  .github-emoji img, .github-emoji .fancybox { margin: 0 !important; padding: 0 !important; border: none !important; outline: none !important; text-decoration: none !important; user-select: none !important; cursor: auto !important; }  .github-emoji img { height: 1.2em !important; width: 1.2em !important; position: absolute !important; left: 50% !important; top: 50% !important; transform: translate(-50%, -50%) !important; user-select: none !important; cursor: auto !important; } .github-emoji-fallback { color: inherit; } .github-emoji-fallback img { opacity: 0 !important; }</style>
</head>




<body>
    <header class="navbar-fixed">
    <nav id="headNav" class="bg-color nav-transparent">
        <div id="navContainer" class="nav-wrapper container">
            <div class="brand-logo">
                <a href="/" class="waves-effect waves-light">
                    
                    <img src="/medias/mj-moon.png" class="logo-img" alt="LOGO">
                    
                    <span class="logo-span">JacksonYoudi</span>
                </a>
            </div>
            

<a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a>
<ul class="right nav-menu">
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/" class="waves-effect waves-light">
      
      <i class="fas fa-home" style="zoom: 0.6;"></i>
      
      <span>首页</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/categories" class="waves-effect waves-light">
      
      <i class="fas fa-bookmark" style="zoom: 0.6;"></i>
      
      <span>分类</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/archives" class="waves-effect waves-light">
      
      <i class="fas fa-archive" style="zoom: 0.6;"></i>
      
      <span>归档</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/tags" class="waves-effect waves-light">
      
      <i class="fas fa-tags" style="zoom: 0.6;"></i>
      
      <span>标签</span>
    </a>
    
  </li>
  
  <li class="hide-on-med-and-down nav-item">
    
    <a href="/about" class="waves-effect waves-light">
      
      <i class="fas fa-user-circle" style="zoom: 0.6;"></i>
      
      <span>关于</span>
    </a>
    
  </li>
  
  <li>
    <a href="#searchModal" class="modal-trigger waves-effect waves-light">
      <i id="searchIcon" class="fas fa-search" title="搜索" style="zoom: 0.85;"></i>
    </a>
  </li>
</ul>


<div id="mobile-nav" class="side-nav sidenav">

    <div class="mobile-head bg-color">
        
        <img src="/medias/mj-moon.png" class="logo-img circle responsive-img">
        
        <div class="logo-name">JacksonYoudi</div>
        <div class="logo-desc">
            
            简单童真
            
        </div>
    </div>

    

    <ul class="menu-list mobile-menu-list">
        
        <li class="m-nav-item">
	  
		<a href="/" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-home"></i>
			
			首页
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/categories" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-bookmark"></i>
			
			分类
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/archives" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-archive"></i>
			
			归档
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/tags" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-tags"></i>
			
			标签
		</a>
          
        </li>
        
        <li class="m-nav-item">
	  
		<a href="/about" class="waves-effect waves-light">
			
			    <i class="fa-fw fas fa-user-circle"></i>
			
			关于
		</a>
          
        </li>
        
        
        <li><div class="divider"></div></li>
        <li>
            <a href="https://github.com/jacksonyoudi" class="waves-effect waves-light" target="_blank">
                <i class="fab fa-github-square fa-fw"></i>Fork Me
            </a>
        </li>
        
    </ul>
</div>


        </div>

        
            <style>
    .nav-transparent .github-corner {
        display: none !important;
    }

    .github-corner {
        position: absolute;
        z-index: 10;
        top: 0;
        right: 0;
        border: 0;
        transform: scale(1.1);
    }

    .github-corner svg {
        color: #0f9d58;
        fill: #fff;
        height: 64px;
        width: 64px;
    }

    .github-corner:hover .octo-arm {
        animation: a 0.56s ease-in-out;
    }

    .github-corner .octo-arm {
        animation: none;
    }

    @keyframes a {
        0%,
        to {
            transform: rotate(0);
        }
        20%,
        60% {
            transform: rotate(-25deg);
        }
        40%,
        80% {
            transform: rotate(10deg);
        }
    }
</style>

<a href="https://github.com/jacksonyoudi" class="github-corner tooltipped hide-on-med-and-down" target="_blank"
   data-tooltip="Fork Me" data-position="left" data-delay="50">
    <svg viewBox="0 0 250 250" aria-hidden="true">
        <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
        <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
              fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
        <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
              fill="currentColor" class="octo-body"></path>
    </svg>
</a>
        
    </nav>

</header>

    



<div class="bg-cover pd-header post-cover" style="background-image: url('/medias/featureimages/14.jpg')">
    <div class="container" style="right: 0px;left: 0px;">
        <div class="row">
            <div class="col s12 m12 l12">
                <div class="brand">
                    <h1 class="description center-align post-title">supervisor源码解析</h1>
                </div>
            </div>
        </div>
    </div>
</div>




<main class="post-container content">

    
    <link rel="stylesheet" href="/libs/tocbot/tocbot.css">
<style>
    #articleContent h1::before,
    #articleContent h2::before,
    #articleContent h3::before,
    #articleContent h4::before,
    #articleContent h5::before,
    #articleContent h6::before {
        display: block;
        content: " ";
        height: 100px;
        margin-top: -100px;
        visibility: hidden;
    }

    #articleContent :focus {
        outline: none;
    }

    .toc-fixed {
        position: fixed;
        top: 64px;
    }

    .toc-widget {
        width: 345px;
        padding-left: 20px;
    }

    .toc-widget .toc-title {
        padding: 35px 0 15px 17px;
        font-size: 1.5rem;
        font-weight: bold;
        line-height: 1.5rem;
    }

    .toc-widget ol {
        padding: 0;
        list-style: none;
    }

    #toc-content {
        padding-bottom: 30px;
        overflow: auto;
    }

    #toc-content ol {
        padding-left: 10px;
    }

    #toc-content ol li {
        padding-left: 10px;
    }

    #toc-content .toc-link:hover {
        color: #42b983;
        font-weight: 700;
        text-decoration: underline;
    }

    #toc-content .toc-link::before {
        background-color: transparent;
        max-height: 25px;

        position: absolute;
        right: 23.5vw;
        display: block;
    }

    #toc-content .is-active-link {
        color: #42b983;
    }

    #floating-toc-btn {
        position: fixed;
        right: 15px;
        bottom: 76px;
        padding-top: 15px;
        margin-bottom: 0;
        z-index: 998;
    }

    #floating-toc-btn .btn-floating {
        width: 48px;
        height: 48px;
    }

    #floating-toc-btn .btn-floating i {
        line-height: 48px;
        font-size: 1.4rem;
    }
</style>
<div class="row">
    <div id="main-content" class="col s12 m12 l9">
        <!-- 文章内容详情 -->
<div id="artDetail">
    <div class="card">
        <div class="card-content article-info">
            <div class="row tag-cate">
                <div class="col s7">
                    
                    <div class="article-tag">
                        
                            <a href="/tags/go/">
                                <span class="chip bg-color">go</span>
                            </a>
                        
                            <a href="/tags/supervisor/">
                                <span class="chip bg-color">supervisor</span>
                            </a>
                        
                            <a href="/tags/%E6%BA%90%E7%A0%81/">
                                <span class="chip bg-color">源码</span>
                            </a>
                        
                            <a href="/tags/python/">
                                <span class="chip bg-color">python</span>
                            </a>
                        
                    </div>
                    
                </div>
                <div class="col s5 right-align">
                    
                    <div class="post-cate">
                        <i class="fas fa-bookmark fa-fw icon-category"></i>
                        
                            <a href="/categories/%E6%8A%80%E6%9C%AF/" class="post-category">
                                技术
                            </a>
                        
                    </div>
                    
                </div>
            </div>

            <div class="post-info">
                
                <div class="post-date info-break-policy">
                    <i class="far fa-calendar-minus fa-fw"></i>发布日期:&nbsp;&nbsp;
                    2021-08-01
                </div>
                

                

                

                

                
            </div>
        </div>
        <hr class="clearfix">

        
        <!-- 是否加载使用自带的 prismjs. -->
        <link rel="stylesheet" href="/libs/prism/prism.css">
        

        

        <div class="card-content article-card-content">
            <div id="articleContent">
                <p><img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/mTUPK0.jpg"></p>
<p>今天介绍一下supervisor的源码。 supervisor是python写的。如果你不懂python，我也介绍一下golang版的实现。 如果你不会，其他语言的实现，应该也有，github找一下。 自己读一下。实现原理应该都是一样的。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/Supervisor/supervisor">源码</a></p>
<h2 id="supervisor的组件"><a href="#supervisor的组件" class="headerlink" title="supervisor的组件"></a>supervisor的组件</h2><h3 id="1-supervisord"><a href="#1-supervisord" class="headerlink" title="1. supervisord"></a>1. supervisord</h3><blockquote>
<p>服务器主进程名为supervisord。它负责在自己的调用中启动子程序，响应来自客户端的命令，重新启动崩溃或退出的子进程，记录其子进程stdout和stderr 输出，以及生成和处理与子进程生命周期中的点相对应的“事件”。</p>
</blockquote>
<p>服务器进程使用配置文件。这通常位于/etc/supervisord.conf中。此配置文件是“Windows-INI”样式配置文件。通过适当的文件系统权限保持此文件的安全非常重要，因为它可能包含未加密的用户名和密码。</p>
<h3 id="2-supervisorctl"><a href="#2-supervisorctl" class="headerlink" title="2. supervisorctl"></a>2. supervisorctl</h3><p>主进程的命令行客户端部分名为 supervisorctl。它为supervisord提供的功能提供了类似shell的界面。从 supervisorctl，用户可以连接到不同的 supervisord进程（一次一个），获取由子进程控制的状态，停止和启动子进程，并获取supervisord的运行进程列表。</p>
<p>命令行客户机通过UNIX域套接字或internet (TCP)套接字与服务器通信。服务器可以断言客户机的用户应该在执行命令之前提供身份验证凭据。客户机进程通常使用与服务器相同的配置文件，但是其中包含[supervisorctl]部分的任何配置文件都可以工作。</p>
<h3 id="3-Web-Server"><a href="#3-Web-Server" class="headerlink" title="3. Web Server"></a>3. Web Server</h3><p>如果您针对internet套接字启动了adminord，那么可以通过浏览器访问具有与supervise orctl类似功能的(稀疏的)web用户界面。在激活配置文件的<code>[inet_http_server]</code>部分之后，访问服务器URL(例如<code>http://localhost:9001/</code>)，通过web界面查看和控制进程状态。</p>
<h3 id="4-XML-RPC-Interface"><a href="#4-XML-RPC-Interface" class="headerlink" title="4. XML-RPC Interface"></a>4. XML-RPC Interface</h3><p>服务于web UI的同一个HTTP服务器提供一个XML-RPC接口，该接口可用于询问和控制管理器及其运行的程序。参见XML-RPC API文档。</p>
<h3 id="5-目录结构"><a href="#5-目录结构" class="headerlink" title="5. 目录结构"></a>5. 目录结构</h3><p>整体看一下目录结构：</p>
<pre class="line-numbers language-bash" data-language="bash"><code class="language-bash">├── __init__.py
├── childutils.py
├── compat.py
├── confecho.py
├── datatypes.py
├── dispatchers.py
├── events.py
├── http.py
├── http_client.py
├── loggers.py
├── medusa
│   ├── CHANGES.txt
│   ├── LICENSE.txt
│   ├── README.txt
│   ├── TODO.txt
│   ├── __init__.py
│   ├── asynchat_25.py
│   ├── asyncore_25.py
│   ├── auth_handler.py
│   ├── counter.py
│   ├── default_handler.py
│   ├── docs
│   │   ├── README.html
│   │   ├── async_blurbs.txt
│   │   ├── composing_producers.gif
│   │   ├── data_flow.gif
│   │   ├── data_flow.html
│   │   ├── producers.gif
│   │   ├── programming.html
│   │   ├── proxy_notes.txt
│   │   ├── threads.txt
│   │   └── tkinter.txt
│   ├── filesys.py
│   ├── http_date.py
│   ├── http_server.py
│   ├── logger.py
│   ├── producers.py
│   ├── util.py
│   └── xmlrpc_handler.py
├── options.py
├── pidproxy.py
├── poller.py
├── process.py
├── rpcinterface.py
├── scripts
│   ├── loop_eventgen.py
│   ├── loop_listener.py
│   ├── sample_commevent.py
│   ├── sample_eventlistener.py
│   └── sample_exiting_eventlistener.py
├── skel
│   └── sample.conf
├── socket_manager.py
├── states.py
├── supervisorctl.py
├── supervisord.py
├── tests
│   ├── __init__.py
│   ├── base.py
│   ├── fixtures
│   │   ├── donothing.conf
│   │   ├── example
│   │   │   └── included.conf
│   │   ├── hello.sh
│   │   ├── include.conf
│   │   ├── issue-1054.conf
│   │   ├── issue-565.conf
│   │   ├── issue-638.conf
│   │   ├── issue-663.conf
│   │   ├── issue-664.conf
│   │   ├── issue-835.conf
│   │   ├── issue-836.conf
│   │   ├── listener.py
│   │   ├── spew.py
│   │   └── unkillable_spew.py
│   ├── test_childutils.py
│   ├── test_confecho.py
│   ├── test_datatypes.py
│   ├── test_dispatchers.py
│   ├── test_end_to_end.py
│   ├── test_events.py
│   ├── test_http.py
│   ├── test_http_client.py
│   ├── test_loggers.py
│   ├── test_options.py
│   ├── test_poller.py
│   ├── test_process.py
│   ├── test_rpcinterfaces.py
│   ├── test_socket_manager.py
│   ├── test_states.py
│   ├── test_supervisorctl.py
│   ├── test_supervisord.py
│   ├── test_web.py
│   └── test_xmlrpc.py
├── ui
│   ├── images
│   │   ├── button_refresh.gif
│   │   ├── button_restart.gif
│   │   ├── button_stop.gif
│   │   ├── icon.png
│   │   ├── rule.gif
│   │   ├── state0.gif
│   │   ├── state1.gif
│   │   ├── state2.gif
│   │   ├── state3.gif
│   │   └── supervisor.gif
│   ├── status.html
│   ├── stylesheets
│   │   └── supervisor.css
│   └── tail.html
├── version.txt
├── web.py
└── xmlrpc.py<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>


<p>整体架构</p>
<p>源码学习按上面的分块进行介绍</p>
<p><img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/t4Mc7M.jpg"></p>
<h2 id="supervisord"><a href="#supervisord" class="headerlink" title="supervisord"></a>supervisord</h2><p>先找到入口程序</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># Main program</span>
<span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span>args<span class="token operator">=</span><span class="token boolean">None</span><span class="token punctuation">,</span> test<span class="token operator">=</span><span class="token boolean">False</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">assert</span> os<span class="token punctuation">.</span>name <span class="token operator">==</span> <span class="token string">"posix"</span><span class="token punctuation">,</span> <span class="token string">"This code makes Unix-specific assumptions"</span>
    <span class="token comment"># if we hup, restart by making a new Supervisor()</span>
    first <span class="token operator">=</span> <span class="token boolean">True</span>
    <span class="token keyword">while</span> <span class="token number">1</span><span class="token punctuation">:</span>
        options <span class="token operator">=</span> ServerOptions<span class="token punctuation">(</span><span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>realize<span class="token punctuation">(</span>args<span class="token punctuation">,</span> doc<span class="token operator">=</span>__doc__<span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>first <span class="token operator">=</span> first
        options<span class="token punctuation">.</span>test <span class="token operator">=</span> test
        <span class="token keyword">if</span> options<span class="token punctuation">.</span>profile_options<span class="token punctuation">:</span>
            sort_order<span class="token punctuation">,</span> callers <span class="token operator">=</span> options<span class="token punctuation">.</span>profile_options
            profile<span class="token punctuation">(</span><span class="token string">'go(options)'</span><span class="token punctuation">,</span> <span class="token builtin">globals</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token builtin">locals</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> sort_order<span class="token punctuation">,</span> callers<span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            go<span class="token punctuation">(</span>options<span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>close_httpservers<span class="token punctuation">(</span><span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>close_logger<span class="token punctuation">(</span><span class="token punctuation">)</span>
        first <span class="token operator">=</span> <span class="token boolean">False</span>
        <span class="token keyword">if</span> test <span class="token keyword">or</span> <span class="token punctuation">(</span>options<span class="token punctuation">.</span>mood <span class="token operator">&lt;</span> SupervisorStates<span class="token punctuation">.</span>RESTARTING<span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">break</span>

<span class="token keyword">if</span> __name__ <span class="token operator">==</span> <span class="token string">"__main__"</span><span class="token punctuation">:</span> <span class="token comment"># pragma: no cover</span>
    main<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>从上面看出， main()中有个死循环一直只工作。<br>下面详细介绍，在循环中做了哪些工作？</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># Main program</span>
<span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span>args<span class="token operator">=</span><span class="token boolean">None</span><span class="token punctuation">,</span> test<span class="token operator">=</span><span class="token boolean">False</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">assert</span> os<span class="token punctuation">.</span>name <span class="token operator">==</span> <span class="token string">"posix"</span><span class="token punctuation">,</span> <span class="token string">"This code makes Unix-specific assumptions"</span>
    <span class="token comment"># if we hup, restart by making a new Supervisor()</span>
    first <span class="token operator">=</span> <span class="token boolean">True</span>
    <span class="token keyword">while</span> <span class="token number">1</span><span class="token punctuation">:</span>
        options <span class="token operator">=</span> ServerOptions<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">//</span> 配置
        options<span class="token punctuation">.</span>realize<span class="token punctuation">(</span>args<span class="token punctuation">,</span> doc<span class="token operator">=</span>__doc__<span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>first <span class="token operator">=</span> first
        options<span class="token punctuation">.</span>test <span class="token operator">=</span> test
        <span class="token keyword">if</span> options<span class="token punctuation">.</span>profile_options<span class="token punctuation">:</span>
            sort_order<span class="token punctuation">,</span> callers <span class="token operator">=</span> options<span class="token punctuation">.</span>profile_options
            profile<span class="token punctuation">(</span><span class="token string">'go(options)'</span><span class="token punctuation">,</span> <span class="token builtin">globals</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token builtin">locals</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> sort_order<span class="token punctuation">,</span> callers<span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            go<span class="token punctuation">(</span>options<span class="token punctuation">)</span> <span class="token operator">//</span> 加载配置开始运行
        options<span class="token punctuation">.</span>close_httpservers<span class="token punctuation">(</span><span class="token punctuation">)</span>
        options<span class="token punctuation">.</span>close_logger<span class="token punctuation">(</span><span class="token punctuation">)</span>
        first <span class="token operator">=</span> <span class="token boolean">False</span>
        <span class="token keyword">if</span> test <span class="token keyword">or</span> <span class="token punctuation">(</span>options<span class="token punctuation">.</span>mood <span class="token operator">&lt;</span> SupervisorStates<span class="token punctuation">.</span>RESTARTING<span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">break</span>

<span class="token keyword">def</span> <span class="token function">go</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token comment"># pragma: no cover</span>
    d <span class="token operator">=</span> Supervisor<span class="token punctuation">(</span>options<span class="token punctuation">)</span> <span class="token operator">//</span> 实例化一个Supervisor对象
    <span class="token keyword">try</span><span class="token punctuation">:</span>
    d<span class="token punctuation">.</span>main<span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token operator">//</span> 运行main<span class="token punctuation">(</span><span class="token punctuation">)</span>函数
    <span class="token keyword">except</span> asyncore<span class="token punctuation">.</span>ExitNow<span class="token punctuation">:</span>
        <span class="token keyword">pass</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<h3 id="Supervisor类的代码"><a href="#Supervisor类的代码" class="headerlink" title="Supervisor类的代码"></a><code>Supervisor</code>类的代码</h3><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">class</span> <span class="token class-name">Supervisor</span><span class="token punctuation">:</span>
    stopping <span class="token operator">=</span> <span class="token boolean">False</span>  <span class="token comment"># set after we detect that we are handling a stop request</span>
    lastshutdownreport <span class="token operator">=</span> <span class="token number">0</span>  <span class="token comment"># throttle for delayed process error reports at stop</span>
    process_groups <span class="token operator">=</span> <span class="token boolean">None</span>  <span class="token comment"># map of process group name to process group object</span>
    stop_groups <span class="token operator">=</span> <span class="token boolean">None</span>  <span class="token comment"># list used for priority ordered shutdown</span>

    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> options<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token comment"># 初始化</span>
        self<span class="token punctuation">.</span>options <span class="token operator">=</span> options <span class="token comment"># 配置</span>
        self<span class="token punctuation">.</span>process_groups <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
        self<span class="token punctuation">.</span>ticks <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

    <span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>first<span class="token punctuation">:</span>
            <span class="token comment"># prevent crash on libdispatch-based systems, at least for the</span>
            <span class="token comment"># first request</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>cleanup_fds<span class="token punctuation">(</span><span class="token punctuation">)</span>

        self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>set_uid_or_exit<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">if</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>first<span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>set_rlimits_or_exit<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token comment"># this sets the options.logger object</span>
        <span class="token comment"># delay logger instantiation until after setuid</span>
        self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>make_logger<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">if</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>nocleanup<span class="token punctuation">:</span>
            <span class="token comment"># clean up old automatic logs</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>clear_autochildlogdir<span class="token punctuation">(</span><span class="token punctuation">)</span>

        self<span class="token punctuation">.</span>run<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment"># 运行</span>

    <span class="token keyword">def</span> <span class="token function">run</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>process_groups <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>  <span class="token comment"># clear</span>
        self<span class="token punctuation">.</span>stop_groups <span class="token operator">=</span> <span class="token boolean">None</span>  <span class="token comment"># clear</span>
        events<span class="token punctuation">.</span>clear<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token comment"># 根据配置进行添加process</span>
            <span class="token keyword">for</span> config <span class="token keyword">in</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>process_group_configs<span class="token punctuation">:</span>
                self<span class="token punctuation">.</span>add_process_group<span class="token punctuation">(</span>config<span class="token punctuation">)</span>
            <span class="token comment"># 进程环境</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>process_environment<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># 打开http web</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>openhttpservers<span class="token punctuation">(</span>self<span class="token punctuation">)</span>
            <span class="token comment"># 用于捕获信号</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>setsignals<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># 主进程是否成为守护进程</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">not</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>nodaemon<span class="token punctuation">)</span> <span class="token keyword">and</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>first<span class="token punctuation">:</span>
                self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>daemonize<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># writing pid file needs to come *after* daemonizing or pid</span>
            <span class="token comment"># will be wrong</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>write_pidfile<span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token comment"># 运行异步io服务器</span>
            self<span class="token punctuation">.</span>runforever<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">finally</span><span class="token punctuation">:</span>
            <span class="token comment"># 异常退出，清理工作</span>
            self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>cleanup<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p><img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/gPpFtg.jpg"></p>
<p>上面代码只有 <code>self.runforever()</code> 是工作的</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">runforever</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
   <span class="token comment"># 事件通知机制</span>
    events<span class="token punctuation">.</span>notify<span class="token punctuation">(</span>events<span class="token punctuation">.</span>SupervisorRunningEvent<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    timeout <span class="token operator">=</span> <span class="token number">1</span>  <span class="token comment"># this cannot be fewer than the smallest TickEvent (5)</span>
    <span class="token comment"># 获取已经注册的句柄</span>
    socket_map <span class="token operator">=</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>get_socket_map<span class="token punctuation">(</span><span class="token punctuation">)</span>
    
    <span class="token comment"># 这里会一直 运行，相当于守护进程</span>
    <span class="token keyword">while</span> <span class="token number">1</span><span class="token punctuation">:</span>
        <span class="token comment"># 保存运行信息等</span>
        combined_map <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
        combined_map<span class="token punctuation">.</span>update<span class="token punctuation">(</span>socket_map<span class="token punctuation">)</span>
        combined_map<span class="token punctuation">.</span>update<span class="token punctuation">(</span>self<span class="token punctuation">.</span>get_process_map<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        
        <span class="token comment"># 进程信息</span>
        pgroups <span class="token operator">=</span> <span class="token builtin">list</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span>process_groups<span class="token punctuation">.</span>values<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        pgroups<span class="token punctuation">.</span>sort<span class="token punctuation">(</span><span class="token punctuation">)</span>
        
        <span class="token comment"># 根据进程配置开启或关闭进程</span>
        <span class="token keyword">if</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>mood <span class="token operator">&lt;</span> SupervisorStates<span class="token punctuation">.</span>RUNNING<span class="token punctuation">:</span>
            <span class="token keyword">if</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>stopping<span class="token punctuation">:</span>
                <span class="token comment"># first time, set the stopping flag, do a</span>
                <span class="token comment"># notification and set stop_groups</span>
                self<span class="token punctuation">.</span>stopping <span class="token operator">=</span> <span class="token boolean">True</span>
                self<span class="token punctuation">.</span>stop_groups <span class="token operator">=</span> pgroups<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span>
                events<span class="token punctuation">.</span>notify<span class="token punctuation">(</span>events<span class="token punctuation">.</span>SupervisorStoppingEvent<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

            self<span class="token punctuation">.</span>ordered_stop_groups_phase_1<span class="token punctuation">(</span><span class="token punctuation">)</span>

            <span class="token keyword">if</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>shutdown_report<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                <span class="token comment"># if there are no unstopped processes (we're done</span>
                <span class="token comment"># killing everything), it's OK to shutdown or reload</span>
                <span class="token keyword">raise</span> asyncore<span class="token punctuation">.</span>ExitNow
                
        <span class="token keyword">for</span> fd<span class="token punctuation">,</span> dispatcher <span class="token keyword">in</span> combined_map<span class="token punctuation">.</span>items<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> dispatcher<span class="token punctuation">.</span>readable<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>poller<span class="token punctuation">.</span>register_readable<span class="token punctuation">(</span>fd<span class="token punctuation">)</span>
            <span class="token keyword">if</span> dispatcher<span class="token punctuation">.</span>writable<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>poller<span class="token punctuation">.</span>register_writable<span class="token punctuation">(</span>fd<span class="token punctuation">)</span>
        <span class="token comment"># poll操作</span>
        r<span class="token punctuation">,</span> w <span class="token operator">=</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>poller<span class="token punctuation">.</span>poll<span class="token punctuation">(</span>timeout<span class="token punctuation">)</span>

        <span class="token keyword">for</span> fd <span class="token keyword">in</span> r<span class="token punctuation">:</span>
            <span class="token keyword">if</span> fd <span class="token keyword">in</span> combined_map<span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    dispatcher <span class="token operator">=</span> combined_map<span class="token punctuation">[</span>fd<span class="token punctuation">]</span>
                    self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>logger<span class="token punctuation">.</span>blather<span class="token punctuation">(</span>
                        <span class="token string">'read event caused by %(dispatcher)r'</span><span class="token punctuation">,</span>
                        dispatcher<span class="token operator">=</span>dispatcher<span class="token punctuation">)</span>
                    dispatcher<span class="token punctuation">.</span>handle_read_event<span class="token punctuation">(</span><span class="token punctuation">)</span>
                    <span class="token keyword">if</span> <span class="token keyword">not</span> dispatcher<span class="token punctuation">.</span>readable<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                        self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>poller<span class="token punctuation">.</span>unregister_readable<span class="token punctuation">(</span>fd<span class="token punctuation">)</span>
                <span class="token keyword">except</span> asyncore<span class="token punctuation">.</span>ExitNow<span class="token punctuation">:</span>
                    <span class="token keyword">raise</span>
                <span class="token keyword">except</span><span class="token punctuation">:</span>
                    combined_map<span class="token punctuation">[</span>fd<span class="token punctuation">]</span><span class="token punctuation">.</span>handle_error<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment"># 依次遍历注册的文件句柄</span>
        <span class="token keyword">for</span> fd <span class="token keyword">in</span> w<span class="token punctuation">:</span>
            <span class="token keyword">if</span> fd <span class="token keyword">in</span> combined_map<span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    dispatcher <span class="token operator">=</span> combined_map<span class="token punctuation">[</span>fd<span class="token punctuation">]</span>
                    self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>logger<span class="token punctuation">.</span>blather<span class="token punctuation">(</span>
                        <span class="token string">'write event caused by %(dispatcher)r'</span><span class="token punctuation">,</span>
                        dispatcher<span class="token operator">=</span>dispatcher<span class="token punctuation">)</span>
                    dispatcher<span class="token punctuation">.</span>handle_write_event<span class="token punctuation">(</span><span class="token punctuation">)</span>
                    <span class="token keyword">if</span> <span class="token keyword">not</span> dispatcher<span class="token punctuation">.</span>writable<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                        self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>poller<span class="token punctuation">.</span>unregister_writable<span class="token punctuation">(</span>fd<span class="token punctuation">)</span>
                <span class="token keyword">except</span> asyncore<span class="token punctuation">.</span>ExitNow<span class="token punctuation">:</span>
                    <span class="token keyword">raise</span>
                <span class="token keyword">except</span><span class="token punctuation">:</span>
                    combined_map<span class="token punctuation">[</span>fd<span class="token punctuation">]</span><span class="token punctuation">.</span>handle_error<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">for</span> group <span class="token keyword">in</span> pgroups<span class="token punctuation">:</span>
            group<span class="token punctuation">.</span>transition<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token comment"># 获取已经死亡的子进程信息</span>
        self<span class="token punctuation">.</span>reap<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment"># 处理信号</span>
        self<span class="token punctuation">.</span>handle_signal<span class="token punctuation">(</span><span class="token punctuation">)</span>
        
        <span class="token comment"># tick时钟</span>
        self<span class="token punctuation">.</span>tick<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">if</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>mood <span class="token operator">&lt;</span> SupervisorStates<span class="token punctuation">.</span>RUNNING<span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>ordered_stop_groups_phase_2<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">if</span> self<span class="token punctuation">.</span>options<span class="token punctuation">.</span>test<span class="token punctuation">:</span>
            <span class="token keyword">break</span>
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/kJHHD0.jpg"></p>
<h3 id="管理process"><a href="#管理process" class="headerlink" title="管理process"></a>管理process</h3><p>下面详细介绍一下如何管理一个process：<br>下面图可以指导主要是</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python">
<span class="token keyword">def</span> <span class="token function">add_process_group</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> config<span class="token punctuation">)</span><span class="token punctuation">:</span>
    name <span class="token operator">=</span> config<span class="token punctuation">.</span>name
    <span class="token keyword">if</span> name <span class="token keyword">not</span> <span class="token keyword">in</span> self<span class="token punctuation">.</span>process_groups<span class="token punctuation">:</span>
        config<span class="token punctuation">.</span>after_setuid<span class="token punctuation">(</span><span class="token punctuation">)</span>
        
        <span class="token comment"># 根据初始化后的配置文件生成相应的子进程实例</span>
        self<span class="token punctuation">.</span>process_groups<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> config<span class="token punctuation">.</span>make_group<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment"># 添加事件通知</span>
        events<span class="token punctuation">.</span>notify<span class="token punctuation">(</span>events<span class="token punctuation">.</span>ProcessGroupAddedEvent<span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">True</span>
    <span class="token keyword">return</span> <span class="token boolean">False</span>
  <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>在supervisor配置中，我们需要写上执行的文件以及执行环境env. 所以，我们围绕 <code>执行这个程序的逻辑就可以了</code></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">execve</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> filename<span class="token punctuation">,</span> argv<span class="token punctuation">,</span> env<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">return</span> os<span class="token punctuation">.</span>execve<span class="token punctuation">(</span>filename<span class="token punctuation">,</span> argv<span class="token punctuation">,</span> env<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre>

<p>作者将所有的process或event的配置 都绑定到 <code>options</code>的对象上， 包括执行的程序以及各种状态， 然后一个deamon程序一直在运行，去实时检查配置是否发生变化了。做对应的操作。</p>
<h3 id="supervisorclt"><a href="#supervisorclt" class="headerlink" title="supervisorclt"></a>supervisorclt</h3><p>这个客户端功能：</p>
<ol>
<li>需要有一个UI,实现是cli</li>
<li>与server通信</li>
</ol>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">main</span><span class="token punctuation">(</span>args<span class="token operator">=</span><span class="token boolean">None</span><span class="token punctuation">,</span> options<span class="token operator">=</span><span class="token boolean">None</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">if</span> options <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
       <span class="token comment"># 实例化对象</span>
        options <span class="token operator">=</span> ClientOptions<span class="token punctuation">(</span><span class="token punctuation">)</span>

    options<span class="token punctuation">.</span>realize<span class="token punctuation">(</span>args<span class="token punctuation">,</span> doc<span class="token operator">=</span>__doc__<span class="token punctuation">)</span>
    <span class="token comment"># 控制器</span>
    c <span class="token operator">=</span> Controller<span class="token punctuation">(</span>options<span class="token punctuation">)</span>

    <span class="token keyword">if</span> options<span class="token punctuation">.</span>args<span class="token punctuation">:</span>
        c<span class="token punctuation">.</span>onecmd<span class="token punctuation">(</span><span class="token string">" "</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>options<span class="token punctuation">.</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span>
        sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span>c<span class="token punctuation">.</span>exitstatus<span class="token punctuation">)</span>
    
    <span class="token comment"># 如果是交互模式</span>
    <span class="token keyword">if</span> options<span class="token punctuation">.</span>interactive<span class="token punctuation">:</span>
        <span class="token comment"># 一直loop, 图形编程常见操作模式</span>
        c<span class="token punctuation">.</span>exec_cmdloop<span class="token punctuation">(</span>args<span class="token punctuation">,</span> options<span class="token punctuation">)</span>
        sys<span class="token punctuation">.</span>exit<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>  <span class="token comment"># exitstatus always 0 for interactive mode</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>我们看交互式的逻辑，<code>exec_cmdloop</code></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># 控制器的method</span>
<span class="token keyword">def</span> <span class="token function">exec_cmdloop</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> args<span class="token punctuation">,</span> options<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token keyword">import</span> readline
        delims <span class="token operator">=</span> readline<span class="token punctuation">.</span>get_completer_delims<span class="token punctuation">(</span><span class="token punctuation">)</span>
        delims <span class="token operator">=</span> delims<span class="token punctuation">.</span>replace<span class="token punctuation">(</span><span class="token string">':'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>  <span class="token comment"># "group:process" as one word</span>
        delims <span class="token operator">=</span> delims<span class="token punctuation">.</span>replace<span class="token punctuation">(</span><span class="token string">'*'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>  <span class="token comment"># "group:*" as one word</span>
        delims <span class="token operator">=</span> delims<span class="token punctuation">.</span>replace<span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span>  <span class="token comment"># names with "-" as one word</span>
        readline<span class="token punctuation">.</span>set_completer_delims<span class="token punctuation">(</span>delims<span class="token punctuation">)</span>

        <span class="token keyword">if</span> options<span class="token punctuation">.</span>history_file<span class="token punctuation">:</span>
            <span class="token keyword">try</span><span class="token punctuation">:</span>
                readline<span class="token punctuation">.</span>read_history_file<span class="token punctuation">(</span>options<span class="token punctuation">.</span>history_file<span class="token punctuation">)</span>
            <span class="token keyword">except</span> IOError<span class="token punctuation">:</span>
                <span class="token keyword">pass</span>

            <span class="token keyword">def</span> <span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    readline<span class="token punctuation">.</span>write_history_file<span class="token punctuation">(</span>options<span class="token punctuation">.</span>history_file<span class="token punctuation">)</span>
                <span class="token keyword">except</span> IOError<span class="token punctuation">:</span>
                    <span class="token keyword">pass</span>

            <span class="token keyword">import</span> atexit
            atexit<span class="token punctuation">.</span>register<span class="token punctuation">(</span>save<span class="token punctuation">)</span>
    <span class="token keyword">except</span> ImportError<span class="token punctuation">:</span>
        <span class="token keyword">pass</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>cmdqueue<span class="token punctuation">.</span>append<span class="token punctuation">(</span><span class="token string">'status'</span><span class="token punctuation">)</span>
        <span class="token comment"># cmdloop</span>
        self<span class="token punctuation">.</span>cmdloop<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">except</span> KeyboardInterrupt<span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>output<span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span>
        <span class="token keyword">pass</span>
   
<span class="token comment"># cmdloop method定义  </span>
<span class="token keyword">def</span> <span class="token function">cmdloop</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> intro<span class="token operator">=</span><span class="token boolean">None</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token triple-quoted-string string">"""Repeatedly issue a prompt, accept input, parse an initial prefix
    off the received input, and dispatch to action methods, passing them
    the remainder of the line as argument.

    """</span>

    self<span class="token punctuation">.</span>preloop<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment"># 输入和快捷键</span>
    <span class="token keyword">if</span> self<span class="token punctuation">.</span>use_rawinput <span class="token keyword">and</span> self<span class="token punctuation">.</span>completekey<span class="token punctuation">:</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token keyword">import</span> readline
            self<span class="token punctuation">.</span>old_completer <span class="token operator">=</span> readline<span class="token punctuation">.</span>get_completer<span class="token punctuation">(</span><span class="token punctuation">)</span>
            readline<span class="token punctuation">.</span>set_completer<span class="token punctuation">(</span>self<span class="token punctuation">.</span>complete<span class="token punctuation">)</span>
            readline<span class="token punctuation">.</span>parse_and_bind<span class="token punctuation">(</span>self<span class="token punctuation">.</span>completekey<span class="token operator">+</span><span class="token string">": complete"</span><span class="token punctuation">)</span>
        <span class="token keyword">except</span> ImportError<span class="token punctuation">:</span>
            <span class="token keyword">pass</span>
    <span class="token keyword">try</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> intro <span class="token keyword">is</span> <span class="token keyword">not</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>intro <span class="token operator">=</span> intro
        <span class="token keyword">if</span> self<span class="token punctuation">.</span>intro<span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span>write<span class="token punctuation">(</span><span class="token builtin">str</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span>intro<span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">"\n"</span><span class="token punctuation">)</span>
        stop <span class="token operator">=</span> <span class="token boolean">None</span>
        <span class="token keyword">while</span> <span class="token keyword">not</span> stop<span class="token punctuation">:</span>
            <span class="token keyword">if</span> self<span class="token punctuation">.</span>cmdqueue<span class="token punctuation">:</span>
                line <span class="token operator">=</span> self<span class="token punctuation">.</span>cmdqueue<span class="token punctuation">.</span>pop<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                <span class="token keyword">if</span> self<span class="token punctuation">.</span>use_rawinput<span class="token punctuation">:</span>
                    <span class="token keyword">try</span><span class="token punctuation">:</span>
                        line <span class="token operator">=</span> <span class="token builtin">input</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span>prompt<span class="token punctuation">)</span>
                    <span class="token keyword">except</span> EOFError<span class="token punctuation">:</span>
                        line <span class="token operator">=</span> <span class="token string">'EOF'</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    self<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span>write<span class="token punctuation">(</span>self<span class="token punctuation">.</span>prompt<span class="token punctuation">)</span>
                    self<span class="token punctuation">.</span>stdout<span class="token punctuation">.</span>flush<span class="token punctuation">(</span><span class="token punctuation">)</span>
                    line <span class="token operator">=</span> self<span class="token punctuation">.</span>stdin<span class="token punctuation">.</span>readline<span class="token punctuation">(</span><span class="token punctuation">)</span>
                    <span class="token keyword">if</span> <span class="token keyword">not</span> <span class="token builtin">len</span><span class="token punctuation">(</span>line<span class="token punctuation">)</span><span class="token punctuation">:</span>
                        line <span class="token operator">=</span> <span class="token string">'EOF'</span>
                    <span class="token keyword">else</span><span class="token punctuation">:</span>
                        line <span class="token operator">=</span> line<span class="token punctuation">.</span>rstrip<span class="token punctuation">(</span><span class="token string">'\r\n'</span><span class="token punctuation">)</span>
            line <span class="token operator">=</span> self<span class="token punctuation">.</span>precmd<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
            stop <span class="token operator">=</span> self<span class="token punctuation">.</span>onecmd<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
            stop <span class="token operator">=</span> self<span class="token punctuation">.</span>postcmd<span class="token punctuation">(</span>stop<span class="token punctuation">,</span> line<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>postloop<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">finally</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> self<span class="token punctuation">.</span>use_rawinput <span class="token keyword">and</span> self<span class="token punctuation">.</span>completekey<span class="token punctuation">:</span>
            <span class="token keyword">try</span><span class="token punctuation">:</span>
                <span class="token keyword">import</span> readline
                readline<span class="token punctuation">.</span>set_completer<span class="token punctuation">(</span>self<span class="token punctuation">.</span>old_completer<span class="token punctuation">)</span>
            <span class="token keyword">except</span> ImportError<span class="token punctuation">:</span>
                <span class="token keyword">pass</span>
        <span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>

<p>上面执行又会执行到<code>onecmd</code></p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">onecmd</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> line<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token triple-quoted-string string">"""Interpret the argument as though it had been typed in response
    to the prompt.

    This may be overridden, but should not normally need to be;
    see the precmd() and postcmd() methods for useful execution hooks.
    The return value is a flag indicating whether interpretation of
    commands by the interpreter should stop.

    """</span>
    cmd<span class="token punctuation">,</span> arg<span class="token punctuation">,</span> line <span class="token operator">=</span> self<span class="token punctuation">.</span>parseline<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token keyword">not</span> line<span class="token punctuation">:</span>
        <span class="token keyword">return</span> self<span class="token punctuation">.</span>emptyline<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> cmd <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
        <span class="token keyword">return</span> self<span class="token punctuation">.</span>default<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
    self<span class="token punctuation">.</span>lastcmd <span class="token operator">=</span> line
    <span class="token keyword">if</span> line <span class="token operator">==</span> <span class="token string">'EOF'</span> <span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>lastcmd <span class="token operator">=</span> <span class="token string">''</span>
    <span class="token keyword">if</span> cmd <span class="token operator">==</span> <span class="token string">''</span><span class="token punctuation">:</span>
        <span class="token keyword">return</span> self<span class="token punctuation">.</span>default<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        <span class="token keyword">try</span><span class="token punctuation">:</span>
            func <span class="token operator">=</span> <span class="token builtin">getattr</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> <span class="token string">'do_'</span> <span class="token operator">+</span> cmd<span class="token punctuation">)</span>
        <span class="token keyword">except</span> AttributeError<span class="token punctuation">:</span>
            <span class="token keyword">return</span> self<span class="token punctuation">.</span>default<span class="token punctuation">(</span>line<span class="token punctuation">)</span>
        <span class="token keyword">return</span> func<span class="token punctuation">(</span>arg<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>可以看出 会返回一个<code>func = getattr(self, 'do_' + cmd)</code>,函数调用，是以<code>do_开头的函数</code><br>在supervisorctl的源码文件中， 我们找一个示例</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">do_start</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> arg<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">if</span> <span class="token keyword">not</span> self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>upcheck<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">return</span>

    names <span class="token operator">=</span> arg<span class="token punctuation">.</span>split<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment"># 连接supervisor服务的代理</span>
    supervisor <span class="token operator">=</span> self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>get_supervisor<span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token keyword">if</span> <span class="token keyword">not</span> names<span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span><span class="token string">"Error: start requires a process name"</span><span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>exitstatus <span class="token operator">=</span> LSBInitExitStatuses<span class="token punctuation">.</span>INVALID_ARGS
        self<span class="token punctuation">.</span>help_start<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span>
    
    <span class="token comment"># 开启所有</span>
    <span class="token keyword">if</span> <span class="token string">'all'</span> <span class="token keyword">in</span> names<span class="token punctuation">:</span>
        <span class="token comment"># 调用startAllProcesses函数</span>
        results <span class="token operator">=</span> supervisor<span class="token punctuation">.</span>startAllProcesses<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">for</span> result <span class="token keyword">in</span> results<span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span>self<span class="token punctuation">.</span>_startresult<span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">)</span>
            self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>set_exitstatus_from_xmlrpc_fault<span class="token punctuation">(</span>result<span class="token punctuation">[</span><span class="token string">'status'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> xmlrpc<span class="token punctuation">.</span>Faults<span class="token punctuation">.</span>ALREADY_STARTED<span class="token punctuation">)</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        <span class="token comment"># 逐个关闭</span>
        <span class="token keyword">for</span> name <span class="token keyword">in</span> names<span class="token punctuation">:</span>
            group_name<span class="token punctuation">,</span> process_name <span class="token operator">=</span> split_namespec<span class="token punctuation">(</span>name<span class="token punctuation">)</span>
            <span class="token keyword">if</span> process_name <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    results <span class="token operator">=</span> supervisor<span class="token punctuation">.</span>startProcessGroup<span class="token punctuation">(</span>group_name<span class="token punctuation">)</span>
                    <span class="token keyword">for</span> result <span class="token keyword">in</span> results<span class="token punctuation">:</span>
                        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span>self<span class="token punctuation">.</span>_startresult<span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">)</span>
                        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>set_exitstatus_from_xmlrpc_fault<span class="token punctuation">(</span>result<span class="token punctuation">[</span><span class="token string">'status'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> xmlrpc<span class="token punctuation">.</span>Faults<span class="token punctuation">.</span>ALREADY_STARTED<span class="token punctuation">)</span>
                <span class="token keyword">except</span> xmlrpclib<span class="token punctuation">.</span>Fault <span class="token keyword">as</span> e<span class="token punctuation">:</span>
                    <span class="token keyword">if</span> e<span class="token punctuation">.</span>faultCode <span class="token operator">==</span> xmlrpc<span class="token punctuation">.</span>Faults<span class="token punctuation">.</span>BAD_NAME<span class="token punctuation">:</span>
                        error <span class="token operator">=</span> <span class="token string">"%s: ERROR (no such group)"</span> <span class="token operator">%</span> group_name
                        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span>error<span class="token punctuation">)</span>
                        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>exitstatus <span class="token operator">=</span> LSBInitExitStatuses<span class="token punctuation">.</span>INVALID_ARGS
                    <span class="token keyword">else</span><span class="token punctuation">:</span>
                        self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>exitstatus <span class="token operator">=</span> LSBInitExitStatuses<span class="token punctuation">.</span>GENERIC
                        <span class="token keyword">raise</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    result <span class="token operator">=</span> supervisor<span class="token punctuation">.</span>startProcess<span class="token punctuation">(</span>name<span class="token punctuation">)</span>
                <span class="token keyword">except</span> xmlrpclib<span class="token punctuation">.</span>Fault <span class="token keyword">as</span> e<span class="token punctuation">:</span>
                    error <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">'status'</span><span class="token punctuation">:</span> e<span class="token punctuation">.</span>faultCode<span class="token punctuation">,</span>
                              <span class="token string">'name'</span><span class="token punctuation">:</span> process_name<span class="token punctuation">,</span>
                              <span class="token string">'group'</span><span class="token punctuation">:</span> group_name<span class="token punctuation">,</span>
                              <span class="token string">'description'</span><span class="token punctuation">:</span> e<span class="token punctuation">.</span>faultString<span class="token punctuation">}</span>
                    self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span>self<span class="token punctuation">.</span>_startresult<span class="token punctuation">(</span>error<span class="token punctuation">)</span><span class="token punctuation">)</span>
                    self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>set_exitstatus_from_xmlrpc_fault<span class="token punctuation">(</span>error<span class="token punctuation">[</span><span class="token string">'status'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> xmlrpc<span class="token punctuation">.</span>Faults<span class="token punctuation">.</span>ALREADY_STARTED<span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    name <span class="token operator">=</span> make_namespec<span class="token punctuation">(</span>group_name<span class="token punctuation">,</span> process_name<span class="token punctuation">)</span>
                    self<span class="token punctuation">.</span>ctl<span class="token punctuation">.</span>output<span class="token punctuation">(</span><span class="token string">'%s: started'</span> <span class="token operator">%</span> name<span class="token punctuation">)</span>


<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p>上面比较重要的就是远程通过rpc调用</p>
<pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">class</span> <span class="token class-name">SupervisorNamespaceRPCInterface</span><span class="token punctuation">:</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token keyword">def</span> <span class="token function">startProcessGroup</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> name<span class="token punctuation">,</span> wait<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">""" Start all processes in the group named 'name'

        @param string name     The group name
        @param boolean wait    Wait for each process to be fully started
        @return array result   An array of process status info structs
        """</span>
        self<span class="token punctuation">.</span>_update<span class="token punctuation">(</span><span class="token string">'startProcessGroup'</span><span class="token punctuation">)</span>

        group <span class="token operator">=</span> self<span class="token punctuation">.</span>supervisord<span class="token punctuation">.</span>process_groups<span class="token punctuation">.</span>get<span class="token punctuation">(</span>name<span class="token punctuation">)</span>

        <span class="token keyword">if</span> group <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
            <span class="token keyword">raise</span> RPCError<span class="token punctuation">(</span>Faults<span class="token punctuation">.</span>BAD_NAME<span class="token punctuation">,</span> name<span class="token punctuation">)</span>

        processes <span class="token operator">=</span> <span class="token builtin">list</span><span class="token punctuation">(</span>group<span class="token punctuation">.</span>processes<span class="token punctuation">.</span>values<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        processes<span class="token punctuation">.</span>sort<span class="token punctuation">(</span><span class="token punctuation">)</span>
        processes <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">(</span>group<span class="token punctuation">,</span> process<span class="token punctuation">)</span> <span class="token keyword">for</span> process <span class="token keyword">in</span> processes <span class="token punctuation">]</span>

        startall <span class="token operator">=</span> make_allfunc<span class="token punctuation">(</span>processes<span class="token punctuation">,</span> isNotRunning<span class="token punctuation">,</span> self<span class="token punctuation">.</span>startProcess<span class="token punctuation">,</span>
                                wait<span class="token operator">=</span>wait<span class="token punctuation">)</span>

        startall<span class="token punctuation">.</span>delay <span class="token operator">=</span> <span class="token number">0.05</span>
        startall<span class="token punctuation">.</span>rpcinterface <span class="token operator">=</span> self
        <span class="token keyword">return</span> startall <span class="token comment"># deferred</span>

<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>


<h3 id="web-UI"><a href="#web-UI" class="headerlink" title="web UI"></a>web UI</h3><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">make_http_servers</span><span class="token punctuation">(</span>options<span class="token punctuation">,</span> supervisord<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">from</span> supervisor<span class="token punctuation">.</span>web <span class="token keyword">import</span> supervisor_ui_handler
    uihandler <span class="token operator">=</span> supervisor_ui_handler<span class="token punctuation">(</span>supervisord<span class="token punctuation">)</span>
    
<span class="token keyword">class</span> <span class="token class-name">supervisor_ui_handler</span><span class="token punctuation">:</span>
    IDENT <span class="token operator">=</span> <span class="token string">'Supervisor Web UI HTTP Request Handler'</span>

    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> supervisord<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>supervisord <span class="token operator">=</span> supervisord

    <span class="token keyword">def</span> <span class="token function">match</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> request<span class="token punctuation">.</span>command <span class="token keyword">not</span> <span class="token keyword">in</span> <span class="token punctuation">(</span><span class="token string">'POST'</span><span class="token punctuation">,</span> <span class="token string">'GET'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">return</span> <span class="token boolean">False</span>

        path<span class="token punctuation">,</span> params<span class="token punctuation">,</span> query<span class="token punctuation">,</span> fragment <span class="token operator">=</span> request<span class="token punctuation">.</span>split_uri<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">while</span> path<span class="token punctuation">.</span>startswith<span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            path <span class="token operator">=</span> path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span>

        <span class="token keyword">if</span> <span class="token keyword">not</span> path<span class="token punctuation">:</span>
            path <span class="token operator">=</span> <span class="token string">'index.html'</span>

        <span class="token keyword">for</span> viewname <span class="token keyword">in</span> VIEWS<span class="token punctuation">.</span>keys<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> viewname <span class="token operator">==</span> path<span class="token punctuation">:</span>
                <span class="token keyword">return</span> <span class="token boolean">True</span>

    <span class="token keyword">def</span> <span class="token function">handle_request</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> request<span class="token punctuation">.</span>command <span class="token operator">==</span> <span class="token string">'POST'</span><span class="token punctuation">:</span>
            request<span class="token punctuation">.</span>collector <span class="token operator">=</span> collector<span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            self<span class="token punctuation">.</span>continue_request<span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">,</span> request<span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">continue_request</span> <span class="token punctuation">(</span>self<span class="token punctuation">,</span> data<span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">:</span>
        form <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
        cgi_env <span class="token operator">=</span> request<span class="token punctuation">.</span>cgi_environment<span class="token punctuation">(</span><span class="token punctuation">)</span>
        form<span class="token punctuation">.</span>update<span class="token punctuation">(</span>cgi_env<span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token string">'QUERY_STRING'</span> <span class="token keyword">not</span> <span class="token keyword">in</span> form<span class="token punctuation">:</span>
            form<span class="token punctuation">[</span><span class="token string">'QUERY_STRING'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">''</span>

        query <span class="token operator">=</span> form<span class="token punctuation">[</span><span class="token string">'QUERY_STRING'</span><span class="token punctuation">]</span>

        <span class="token comment"># we only handle x-www-form-urlencoded values from POSTs</span>
        form_urlencoded <span class="token operator">=</span> parse_qsl<span class="token punctuation">(</span>data<span class="token punctuation">)</span>
        query_data <span class="token operator">=</span> parse_qs<span class="token punctuation">(</span>query<span class="token punctuation">)</span>

        <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token keyword">in</span> query_data<span class="token punctuation">.</span>items<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token comment"># ignore dupes</span>
            form<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> v<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>

        <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token keyword">in</span> form_urlencoded<span class="token punctuation">:</span>
            <span class="token comment"># ignore dupes</span>
            form<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> v

        form<span class="token punctuation">[</span><span class="token string">'SERVER_URL'</span><span class="token punctuation">]</span> <span class="token operator">=</span> request<span class="token punctuation">.</span>get_server_url<span class="token punctuation">(</span><span class="token punctuation">)</span>

        path <span class="token operator">=</span> form<span class="token punctuation">[</span><span class="token string">'PATH_INFO'</span><span class="token punctuation">]</span>
        <span class="token comment"># strip off all leading slashes</span>
        <span class="token keyword">while</span> path <span class="token keyword">and</span> path<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">'/'</span><span class="token punctuation">:</span>
            path <span class="token operator">=</span> path<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span>
        <span class="token keyword">if</span> <span class="token keyword">not</span> path<span class="token punctuation">:</span>
            path <span class="token operator">=</span> <span class="token string">'index.html'</span>

        viewinfo <span class="token operator">=</span> VIEWS<span class="token punctuation">.</span>get<span class="token punctuation">(</span>path<span class="token punctuation">)</span>
        <span class="token keyword">if</span> viewinfo <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
            <span class="token comment"># this should never happen if our match method works</span>
            <span class="token keyword">return</span>

        response <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">'headers'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">}</span>

        viewclass <span class="token operator">=</span> viewinfo<span class="token punctuation">[</span><span class="token string">'view'</span><span class="token punctuation">]</span>
        viewtemplate <span class="token operator">=</span> viewinfo<span class="token punctuation">[</span><span class="token string">'template'</span><span class="token punctuation">]</span>
        context <span class="token operator">=</span> ViewContext<span class="token punctuation">(</span>template<span class="token operator">=</span>viewtemplate<span class="token punctuation">,</span>
                              request <span class="token operator">=</span> request<span class="token punctuation">,</span>
                              form <span class="token operator">=</span> form<span class="token punctuation">,</span>
                              response <span class="token operator">=</span> response<span class="token punctuation">,</span>
                              supervisord<span class="token operator">=</span>self<span class="token punctuation">.</span>supervisord<span class="token punctuation">)</span>
        view <span class="token operator">=</span> viewclass<span class="token punctuation">(</span>context<span class="token punctuation">)</span>
        pushproducer <span class="token operator">=</span> request<span class="token punctuation">.</span>channel<span class="token punctuation">.</span>push_with_producer
        pushproducer<span class="token punctuation">(</span>DeferredWebProducer<span class="token punctuation">(</span>request<span class="token punctuation">,</span> view<span class="token punctuation">)</span><span class="token punctuation">)</span>
    
<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>


<h3 id="RPC"><a href="#RPC" class="headerlink" title="RPC"></a>RPC</h3><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">class</span> <span class="token class-name">supervisor_xmlrpc_handler</span><span class="token punctuation">(</span>xmlrpc_handler<span class="token punctuation">)</span><span class="token punctuation">:</span>
    path <span class="token operator">=</span> <span class="token string">'/RPC2'</span>
    IDENT <span class="token operator">=</span> <span class="token string">'Supervisor XML-RPC Handler'</span>

    unmarshallers <span class="token operator">=</span> <span class="token punctuation">{</span>
        <span class="token string">"int"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"i4"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> <span class="token builtin">int</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"boolean"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> x<span class="token punctuation">.</span>text <span class="token operator">==</span> <span class="token string">"1"</span><span class="token punctuation">,</span>
        <span class="token string">"string"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> x<span class="token punctuation">.</span>text <span class="token keyword">or</span> <span class="token string">""</span><span class="token punctuation">,</span>
        <span class="token string">"double"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> <span class="token builtin">float</span><span class="token punctuation">(</span>x<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"dateTime.iso8601"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> make_datetime<span class="token punctuation">(</span>x<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"array"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> x<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>text<span class="token punctuation">,</span>
        <span class="token string">"data"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> <span class="token punctuation">[</span>v<span class="token punctuation">.</span>text <span class="token keyword">for</span> v <span class="token keyword">in</span> x<span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token string">"struct"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> <span class="token builtin">dict</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">(</span>k<span class="token punctuation">.</span>text <span class="token keyword">or</span> <span class="token string">""</span><span class="token punctuation">,</span> v<span class="token punctuation">.</span>text<span class="token punctuation">)</span> <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token keyword">in</span> x<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"base64"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> as_string<span class="token punctuation">(</span>decodestring<span class="token punctuation">(</span>as_bytes<span class="token punctuation">(</span>x<span class="token punctuation">.</span>text <span class="token keyword">or</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        <span class="token string">"param"</span><span class="token punctuation">:</span> <span class="token keyword">lambda</span> x<span class="token punctuation">:</span> x<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>text<span class="token punctuation">,</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> supervisord<span class="token punctuation">,</span> subinterfaces<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>rpcinterface <span class="token operator">=</span> RootRPCInterface<span class="token punctuation">(</span>subinterfaces<span class="token punctuation">)</span>
        self<span class="token punctuation">.</span>supervisord <span class="token operator">=</span> supervisord

    <span class="token keyword">def</span> <span class="token function">loads</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">:</span>
        params <span class="token operator">=</span> method <span class="token operator">=</span> <span class="token boolean">None</span>
        <span class="token keyword">for</span> action<span class="token punctuation">,</span> elem <span class="token keyword">in</span> iterparse<span class="token punctuation">(</span>StringIO<span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            unmarshall <span class="token operator">=</span> self<span class="token punctuation">.</span>unmarshallers<span class="token punctuation">.</span>get<span class="token punctuation">(</span>elem<span class="token punctuation">.</span>tag<span class="token punctuation">)</span>
            <span class="token keyword">if</span> unmarshall<span class="token punctuation">:</span>
                data <span class="token operator">=</span> unmarshall<span class="token punctuation">(</span>elem<span class="token punctuation">)</span>
                elem<span class="token punctuation">.</span>clear<span class="token punctuation">(</span><span class="token punctuation">)</span>
                elem<span class="token punctuation">.</span>text <span class="token operator">=</span> data
            <span class="token keyword">elif</span> elem<span class="token punctuation">.</span>tag <span class="token operator">==</span> <span class="token string">"value"</span><span class="token punctuation">:</span>
                <span class="token keyword">try</span><span class="token punctuation">:</span>
                    data <span class="token operator">=</span> elem<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>text
                <span class="token keyword">except</span> IndexError<span class="token punctuation">:</span>
                    data <span class="token operator">=</span> elem<span class="token punctuation">.</span>text <span class="token keyword">or</span> <span class="token string">""</span>
                elem<span class="token punctuation">.</span>clear<span class="token punctuation">(</span><span class="token punctuation">)</span>
                elem<span class="token punctuation">.</span>text <span class="token operator">=</span> data
            <span class="token keyword">elif</span> elem<span class="token punctuation">.</span>tag <span class="token operator">==</span> <span class="token string">"methodName"</span><span class="token punctuation">:</span>
                method <span class="token operator">=</span> elem<span class="token punctuation">.</span>text
            <span class="token keyword">elif</span> elem<span class="token punctuation">.</span>tag <span class="token operator">==</span> <span class="token string">"params"</span><span class="token punctuation">:</span>
                params <span class="token operator">=</span> <span class="token builtin">tuple</span><span class="token punctuation">(</span><span class="token punctuation">[</span>v<span class="token punctuation">.</span>text <span class="token keyword">for</span> v <span class="token keyword">in</span> elem<span class="token punctuation">]</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> params<span class="token punctuation">,</span> method

    <span class="token keyword">def</span> <span class="token function">match</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">return</span> request<span class="token punctuation">.</span>uri<span class="token punctuation">.</span>startswith<span class="token punctuation">(</span>self<span class="token punctuation">.</span>path<span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">continue_request</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> data<span class="token punctuation">,</span> request<span class="token punctuation">)</span><span class="token punctuation">:</span>
        logger <span class="token operator">=</span> self<span class="token punctuation">.</span>supervisord<span class="token punctuation">.</span>options<span class="token punctuation">.</span>logger

        <span class="token keyword">try</span><span class="token punctuation">:</span>
            <span class="token keyword">try</span><span class="token punctuation">:</span>
                <span class="token comment"># on 2.x, the Expat parser doesn't like Unicode which actually</span>
                <span class="token comment"># contains non-ASCII characters. It's a bit of a kludge to</span>
                <span class="token comment"># do it conditionally here, but it's down to how underlying</span>
                <span class="token comment"># libs behave</span>
                <span class="token keyword">if</span> PY2<span class="token punctuation">:</span>
                    data <span class="token operator">=</span> data<span class="token punctuation">.</span>encode<span class="token punctuation">(</span><span class="token string">'ascii'</span><span class="token punctuation">,</span> <span class="token string">'xmlcharrefreplace'</span><span class="token punctuation">)</span>
                params<span class="token punctuation">,</span> method <span class="token operator">=</span> self<span class="token punctuation">.</span>loads<span class="token punctuation">(</span>data<span class="token punctuation">)</span>
            <span class="token keyword">except</span><span class="token punctuation">:</span>
                logger<span class="token punctuation">.</span>error<span class="token punctuation">(</span>
                    <span class="token string">'XML-RPC request data %r is invalid: unmarshallable'</span> <span class="token operator">%</span>
                    <span class="token punctuation">(</span>data<span class="token punctuation">,</span><span class="token punctuation">)</span>
                <span class="token punctuation">)</span>
                request<span class="token punctuation">.</span>error<span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span>
                <span class="token keyword">return</span>

            <span class="token comment"># no &lt;methodName&gt; in the request or name is an empty string</span>
            <span class="token keyword">if</span> <span class="token keyword">not</span> method<span class="token punctuation">:</span>
                logger<span class="token punctuation">.</span>error<span class="token punctuation">(</span>
                    <span class="token string">'XML-RPC request data %r is invalid: no method name'</span> <span class="token operator">%</span>
                    <span class="token punctuation">(</span>data<span class="token punctuation">,</span><span class="token punctuation">)</span>
                <span class="token punctuation">)</span>
                request<span class="token punctuation">.</span>error<span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span>
                <span class="token keyword">return</span>

            <span class="token comment"># we allow xml-rpc clients that do not send empty &lt;params&gt;</span>
            <span class="token comment"># when there are no parameters for the method call</span>
            <span class="token keyword">if</span> params <span class="token keyword">is</span> <span class="token boolean">None</span><span class="token punctuation">:</span>
                params <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span>

            <span class="token keyword">try</span><span class="token punctuation">:</span>
                logger<span class="token punctuation">.</span>trace<span class="token punctuation">(</span><span class="token string">'XML-RPC method called: %s()'</span> <span class="token operator">%</span> method<span class="token punctuation">)</span>
                value <span class="token operator">=</span> self<span class="token punctuation">.</span>call<span class="token punctuation">(</span>method<span class="token punctuation">,</span> params<span class="token punctuation">)</span>
                logger<span class="token punctuation">.</span>trace<span class="token punctuation">(</span><span class="token string">'XML-RPC method %s() returned successfully'</span> <span class="token operator">%</span>
                             method<span class="token punctuation">)</span>
            <span class="token keyword">except</span> RPCError <span class="token keyword">as</span> err<span class="token punctuation">:</span>
                <span class="token comment"># turn RPCError reported by method into a Fault instance</span>
                value <span class="token operator">=</span> xmlrpclib<span class="token punctuation">.</span>Fault<span class="token punctuation">(</span>err<span class="token punctuation">.</span>code<span class="token punctuation">,</span> err<span class="token punctuation">.</span>text<span class="token punctuation">)</span>
                logger<span class="token punctuation">.</span>trace<span class="token punctuation">(</span><span class="token string">'XML-RPC method %s() returned fault: [%d] %s'</span> <span class="token operator">%</span> <span class="token punctuation">(</span>
                    method<span class="token punctuation">,</span>
                    err<span class="token punctuation">.</span>code<span class="token punctuation">,</span> err<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">)</span>

            <span class="token keyword">if</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> types<span class="token punctuation">.</span>FunctionType<span class="token punctuation">)</span><span class="token punctuation">:</span>
                <span class="token comment"># returning a function from an RPC method implies that</span>
                <span class="token comment"># this needs to be a deferred response (it needs to block).</span>
                pushproducer <span class="token operator">=</span> request<span class="token punctuation">.</span>channel<span class="token punctuation">.</span>push_with_producer
                pushproducer<span class="token punctuation">(</span>DeferredXMLRPCResponse<span class="token punctuation">(</span>request<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">)</span>

            <span class="token keyword">else</span><span class="token punctuation">:</span>
                <span class="token comment"># if we get anything but a function, it implies that this</span>
                <span class="token comment"># response doesn't need to be deferred, we can service it</span>
                <span class="token comment"># right away.</span>
                body <span class="token operator">=</span> as_bytes<span class="token punctuation">(</span>xmlrpc_marshal<span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span>
                request<span class="token punctuation">[</span><span class="token string">'Content-Type'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'text/xml'</span>
                request<span class="token punctuation">[</span><span class="token string">'Content-Length'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span>
                request<span class="token punctuation">.</span>push<span class="token punctuation">(</span>body<span class="token punctuation">)</span>
                request<span class="token punctuation">.</span>done<span class="token punctuation">(</span><span class="token punctuation">)</span>

        <span class="token keyword">except</span><span class="token punctuation">:</span>
            tb <span class="token operator">=</span> traceback<span class="token punctuation">.</span>format_exc<span class="token punctuation">(</span><span class="token punctuation">)</span>
            logger<span class="token punctuation">.</span>critical<span class="token punctuation">(</span>
                <span class="token string">"Handling XML-RPC request with data %r raised an unexpected "</span>
                <span class="token string">"exception: %s"</span> <span class="token operator">%</span> <span class="token punctuation">(</span>data<span class="token punctuation">,</span> tb<span class="token punctuation">)</span>
            <span class="token punctuation">)</span>
            <span class="token comment"># internal error, report as HTTP server error</span>
            request<span class="token punctuation">.</span>error<span class="token punctuation">(</span><span class="token number">500</span><span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">call</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> method<span class="token punctuation">,</span> params<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">return</span> traverse<span class="token punctuation">(</span>self<span class="token punctuation">.</span>rpcinterface<span class="token punctuation">,</span> method<span class="token punctuation">,</span> params<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>
<p><img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/Hwfzfb.jpg"></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>python是解释型语言 弱类型，看源码没有编译型语言清晰明了。这个源码不太容易看，我参考supervisor的设计写公司项目，一开始是看这个源码，发现很不容易理清楚，我是先看了go语言版的，然后在回头看python版的才看明白。可以直接看go版本的，那个更加清晰。</p>

                
            </div>
            <hr/>

            

    <div class="reprint" id="reprint-statement">
        
            <div class="reprint__author">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-user">
                        文章作者:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="/about" rel="external nofollow noreferrer">Jackson</a>
                </span>
            </div>
            <div class="reprint__type">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-link">
                        文章链接:
                    </i>
                </span>
                <span class="reprint-info">
                    <a href="https://www.jacksonyoudi.com/2021/08/01/supervisor/">https://www.jacksonyoudi.com/2021/08/01/supervisor/</a>
                </span>
            </div>
            <div class="reprint__notice">
                <span class="reprint-meta" style="font-weight: bold;">
                    <i class="fas fa-copyright">
                        版权声明:
                    </i>
                </span>
                <span class="reprint-info">
                    本博客所有文章除特別声明外，均采用
                    <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a>
                    许可协议。转载请注明来源
                    <a href="/about" target="_blank">Jackson</a>
                    !
                </span>
            </div>
        
    </div>

    <script async defer>
      document.addEventListener("copy", function (e) {
        let toastHTML = '<span>复制成功，请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
        M.toast({html: toastHTML})
      });

      function navToReprintStatement() {
        $("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
      }
    </script>



            <div class="tag_share" style="display: block;">
                <div class="post-meta__tag-list" style="display: inline-block;">
                    
                        <div class="article-tag">
                            
                                <a href="/tags/go/">
                                    <span class="chip bg-color">go</span>
                                </a>
                            
                                <a href="/tags/supervisor/">
                                    <span class="chip bg-color">supervisor</span>
                                </a>
                            
                                <a href="/tags/%E6%BA%90%E7%A0%81/">
                                    <span class="chip bg-color">源码</span>
                                </a>
                            
                                <a href="/tags/python/">
                                    <span class="chip bg-color">python</span>
                                </a>
                            
                        </div>
                    
                </div>
                <div class="post_share" style="zoom: 80%; width: fit-content; display: inline-block; float: right; margin: -0.15rem 0;">
                    <link rel="stylesheet" type="text/css" href="/libs/share/css/share.min.css">
<div id="article-share">

    
    <div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享！</p>"></div>
    <script src="/libs/share/js/social-share.min.js"></script>
    

    

</div>

                </div>
            </div>
            
        </div>
    </div>

    

    

    

    

    

    

    

    

    

<article id="prenext-posts" class="prev-next articles">
    <div class="row article-row">
        
        <div class="article col s12 m6" data-aos="fade-up" data-aos="fade-up">
            <div class="article-badge left-badge text-color">
                <i class="far fa-dot-circle"></i>&nbsp;本篇
            </div>
            <div class="card">
                <a href="/2021/08/01/supervisor/">
                    <div class="card-image">
                        
                        
                        <img src="/medias/featureimages/14.jpg" class="responsive-img" alt="supervisor源码解析">
                        
                        <span class="card-title">supervisor源码解析</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            通过源码介绍supervisor，学习一些通用的软件架构和技巧
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2021-08-01
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/%E6%8A%80%E6%9C%AF/" class="post-category">
                                    技术
                                </a>
                            
                            
                        </span>
                    </div>
                </div>

                
                <div class="card-action article-tags">
                    
                    <a href="/tags/go/">
                        <span class="chip bg-color">go</span>
                    </a>
                    
                    <a href="/tags/supervisor/">
                        <span class="chip bg-color">supervisor</span>
                    </a>
                    
                    <a href="/tags/%E6%BA%90%E7%A0%81/">
                        <span class="chip bg-color">源码</span>
                    </a>
                    
                    <a href="/tags/python/">
                        <span class="chip bg-color">python</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
        
        <div class="article col s12 m6" data-aos="fade-up">
            <div class="article-badge right-badge text-color">
                下一篇&nbsp;<i class="fas fa-chevron-right"></i>
            </div>
            <div class="card">
                <a href="/2021/08/01/maven/">
                    <div class="card-image">
                        
                        <img src="https://raw.githubusercontent.com/jacksonyoudi/images/main/uPic/xwoLGY.jpg" class="responsive-img" alt="项目管理工具maven">
                        
                        <span class="card-title">项目管理工具maven</span>
                    </div>
                </a>
                <div class="card-content article-content">
                    <div class="summary block-with-text">
                        
                            介绍maven在开发中使用，以及一些专业术语相关的东西
                        
                    </div>
                    <div class="publish-info">
                            <span class="publish-date">
                                <i class="far fa-clock fa-fw icon-date"></i>2021-08-01
                            </span>
                        <span class="publish-author">
                            
                            <i class="fas fa-bookmark fa-fw icon-category"></i>
                            
                            <a href="/categories/%E5%B7%A5%E5%85%B7%E8%BD%AF%E4%BB%B6/" class="post-category">
                                    工具软件
                                </a>
                            
                            
                        </span>
                    </div>
                </div>
                
                <div class="card-action article-tags">
                    
                    <a href="/tags/java/">
                        <span class="chip bg-color">java</span>
                    </a>
                    
                    <a href="/tags/package-manager/">
                        <span class="chip bg-color">package manager</span>
                    </a>
                    
                    <a href="/tags/maven/">
                        <span class="chip bg-color">maven</span>
                    </a>
                    
                </div>
                
            </div>
        </div>
        
    </div>
</article>

</div>


<script>
    $('#articleContent').on('copy', function (e) {
        // IE8 or earlier browser is 'undefined'
        if (typeof window.getSelection === 'undefined') return;

        var selection = window.getSelection();
        // if the selection is short let's not annoy our users.
        if (('' + selection).length < Number.parseInt('120')) {
            return;
        }

        // create a div outside of the visible area and fill it with the selected text.
        var bodyElement = document.getElementsByTagName('body')[0];
        var newdiv = document.createElement('div');
        newdiv.style.position = 'absolute';
        newdiv.style.left = '-99999px';
        bodyElement.appendChild(newdiv);
        newdiv.appendChild(selection.getRangeAt(0).cloneContents());

        // we need a <pre> tag workaround.
        // otherwise the text inside "pre" loses all the line breaks!
        if (selection.getRangeAt(0).commonAncestorContainer.nodeName === 'PRE' || selection.getRangeAt(0).commonAncestorContainer.nodeName === 'CODE') {
            newdiv.innerHTML = "<pre>" + newdiv.innerHTML + "</pre>";
        }

        var url = document.location.href;
        newdiv.innerHTML += '<br />'
            + '来源: JacksonYoudi<br />'
            + '文章作者: Jackson<br />'
            + '文章链接: <a href="' + url + '">' + url + '</a><br />'
            + '本文章著作权归作者所有，任何形式的转载都请注明出处。';

        selection.selectAllChildren(newdiv);
        window.setTimeout(function () {bodyElement.removeChild(newdiv);}, 200);
    });
</script>


<!-- 代码块功能依赖 -->
<script type="text/javascript" src="/libs/codeBlock/codeBlockFuction.js"></script>

<!-- 代码语言 -->

<script type="text/javascript" src="/libs/codeBlock/codeLang.js"></script>


<!-- 代码块复制 -->

<script type="text/javascript" src="/libs/codeBlock/codeCopy.js"></script>


<!-- 代码块收缩 -->

<script type="text/javascript" src="/libs/codeBlock/codeShrink.js"></script>


    </div>
    <div id="toc-aside" class="expanded col l3 hide-on-med-and-down">
        <div class="toc-widget card" style="background-color: white;">
            <div class="toc-title"><i class="far fa-list-alt"></i>&nbsp;&nbsp;目录</div>
            <div id="toc-content"></div>
        </div>
    </div>
</div>

<!-- TOC 悬浮按钮. -->

<div id="floating-toc-btn" class="hide-on-med-and-down">
    <a class="btn-floating btn-large bg-color">
        <i class="fas fa-list-ul"></i>
    </a>
</div>


<script src="/libs/tocbot/tocbot.min.js"></script>
<script>
    $(function () {
        tocbot.init({
            tocSelector: '#toc-content',
            contentSelector: '#articleContent',
            headingsOffset: -($(window).height() * 0.4 - 45),
            collapseDepth: Number('0'),
            headingSelector: 'h2, h3, h4'
        });

        // modify the toc link href to support Chinese.
        let i = 0;
        let tocHeading = 'toc-heading-';
        $('#toc-content a').each(function () {
            $(this).attr('href', '#' + tocHeading + (++i));
        });

        // modify the heading title id to support Chinese.
        i = 0;
        $('#articleContent').children('h2, h3, h4').each(function () {
            $(this).attr('id', tocHeading + (++i));
        });

        // Set scroll toc fixed.
        let tocHeight = parseInt($(window).height() * 0.4 - 64);
        let $tocWidget = $('.toc-widget');
        $(window).scroll(function () {
            let scroll = $(window).scrollTop();
            /* add post toc fixed. */
            if (scroll > tocHeight) {
                $tocWidget.addClass('toc-fixed');
            } else {
                $tocWidget.removeClass('toc-fixed');
            }
        });

        
        /* 修复文章卡片 div 的宽度. */
        let fixPostCardWidth = function (srcId, targetId) {
            let srcDiv = $('#' + srcId);
            if (srcDiv.length === 0) {
                return;
            }

            let w = srcDiv.width();
            if (w >= 450) {
                w = w + 21;
            } else if (w >= 350 && w < 450) {
                w = w + 18;
            } else if (w >= 300 && w < 350) {
                w = w + 16;
            } else {
                w = w + 14;
            }
            $('#' + targetId).width(w);
        };

        // 切换TOC目录展开收缩的相关操作.
        const expandedClass = 'expanded';
        let $tocAside = $('#toc-aside');
        let $mainContent = $('#main-content');
        $('#floating-toc-btn .btn-floating').click(function () {
            if ($tocAside.hasClass(expandedClass)) {
                $tocAside.removeClass(expandedClass).hide();
                $mainContent.removeClass('l9');
            } else {
                $tocAside.addClass(expandedClass).show();
                $mainContent.addClass('l9');
            }
            fixPostCardWidth('artDetail', 'prenext-posts');
        });
        
    });
</script>

    

</main>




    <footer class="page-footer bg-color">
    

    <div class="container row center-align"
         style="margin-bottom: 0px !important;">
        <div class="col s12 m8 l8 copy-right">
            Copyright&nbsp;&copy;
            
                <span id="year">2019-2021</span>
            
            <span id="year">2019</span>
            <a href="/about" target="_blank">Jackson</a>
            |&nbsp;Powered by&nbsp;<a href="https://hexo.io/" target="_blank">Hexo</a>
            |&nbsp;Theme&nbsp;<a href="https://github.com/blinkfox/hexo-theme-matery" target="_blank">Matery</a>
            <br>
            
            
            
                
            
            
                <span id="busuanzi_container_site_pv">
                &nbsp;|&nbsp;<i class="far fa-eye"></i>&nbsp;总访问量:&nbsp;
                    <span id="busuanzi_value_site_pv" class="white-color"></span>
            </span>
            
            
                <span id="busuanzi_container_site_uv">
                &nbsp;|&nbsp;<i class="fas fa-users"></i>&nbsp;总访问人数:&nbsp;
                    <span id="busuanzi_value_site_uv" class="white-color"></span>
            </span>
            
            <br>

            <!-- 运行天数提醒. -->
            
            <br>
            
        </div>
        <div class="col s12 m4 l4 social-link social-statis">
    <a href="https://github.com/jacksonyoudi" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50">
        <i class="fab fa-github"></i>
    </a>



    <a href="mailto:liangchangyoujackson@gmail.com" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50">
        <i class="fas fa-envelope-open"></i>
    </a>













</div>
    </div>
</footer>

<div class="progress-bar"></div>


    <!-- 搜索遮罩框 -->
<div id="searchModal" class="modal">
    <div class="modal-content">
        <div class="search-header">
            <span class="title"><i class="fas fa-search"></i>&nbsp;&nbsp;搜索</span>
            <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字"
                   class="search-input">
        </div>
        <div id="searchResult"></div>
    </div>
</div>

<script type="text/javascript">
$(function () {
    var searchFunc = function (path, search_id, content_id) {
        'use strict';
        $.ajax({
            url: path,
            dataType: "xml",
            success: function (xmlResponse) {
                // get the contents from search data
                var datas = $("entry", xmlResponse).map(function () {
                    return {
                        title: $("title", this).text(),
                        content: $("content", this).text(),
                        url: $("url", this).text()
                    };
                }).get();
                var $input = document.getElementById(search_id);
                var $resultContent = document.getElementById(content_id);
                $input.addEventListener('input', function () {
                    var str = '<ul class=\"search-result-list\">';
                    var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
                    $resultContent.innerHTML = "";
                    if (this.value.trim().length <= 0) {
                        return;
                    }
                    // perform local searching
                    datas.forEach(function (data) {
                        var isMatch = true;
                        var data_title = data.title.trim().toLowerCase();
                        var data_content = data.content.trim().replace(/<[^>]+>/g, "").toLowerCase();
                        var data_url = data.url;
                        data_url = data_url.indexOf('/') === 0 ? data.url : '/' + data_url;
                        var index_title = -1;
                        var index_content = -1;
                        var first_occur = -1;
                        // only match artiles with not empty titles and contents
                        if (data_title !== '' && data_content !== '') {
                            keywords.forEach(function (keyword, i) {
                                index_title = data_title.indexOf(keyword);
                                index_content = data_content.indexOf(keyword);
                                if (index_title < 0 && index_content < 0) {
                                    isMatch = false;
                                } else {
                                    if (index_content < 0) {
                                        index_content = 0;
                                    }
                                    if (i === 0) {
                                        first_occur = index_content;
                                    }
                                }
                            });
                        }
                        // show search results
                        if (isMatch) {
                            str += "<li><a href='" + data_url + "' class='search-result-title'>" + data_title + "</a>";
                            var content = data.content.trim().replace(/<[^>]+>/g, "");
                            if (first_occur >= 0) {
                                // cut out 100 characters
                                var start = first_occur - 20;
                                var end = first_occur + 80;
                                if (start < 0) {
                                    start = 0;
                                }
                                if (start === 0) {
                                    end = 100;
                                }
                                if (end > content.length) {
                                    end = content.length;
                                }
                                var match_content = content.substr(start, end);
                                // highlight all keywords
                                keywords.forEach(function (keyword) {
                                    var regS = new RegExp(keyword, "gi");
                                    match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
                                });

                                str += "<p class=\"search-result\">" + match_content + "...</p>"
                            }
                            str += "</li>";
                        }
                    });
                    str += "</ul>";
                    $resultContent.innerHTML = str;
                });
            }
        });
    };

    searchFunc('/search.xml', 'searchInput', 'searchResult');
});
</script>

    <!-- 回到顶部按钮 -->
<div id="backTop" class="top-scroll">
    <a class="btn-floating btn-large waves-effect waves-light" href="#!">
        <i class="fas fa-arrow-up"></i>
    </a>
</div>


    <script src="/libs/materialize/materialize.min.js"></script>
    <script src="/libs/masonry/masonry.pkgd.min.js"></script>
    <script src="/libs/aos/aos.js"></script>
    <script src="/libs/scrollprogress/scrollProgress.min.js"></script>
    <script src="/libs/lightGallery/js/lightgallery-all.min.js"></script>
    <script src="/js/matery.js"></script>

    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <script src="/libs/others/clicklove.js" async="async"></script>
    
    
    <script async src="/libs/others/busuanzi.pure.mini.js"></script>
    

    

    

    <!--腾讯兔小巢-->
    
    

    

    

    
    <script src="/libs/instantpage/instantpage.js" type="module"></script>
    

</body>

</html>
